/*-------------------------------------------------------------------------
 *
 * system.c
 *	   Win32 的 system() 和 popen() 替代实现
 *
 *
 *	Win32 在 system() 字符串的开头和结尾需要双引号。如果没有，它会对多个引用字符串感到困惑。它还要求在可执行名称和任何用于重定向的文件周围加上双引号。通过 appendShellString() 过滤其他参数以使用引号。
 *
 *	使用 Win32 "CMD /?" 生成的：
 *
 *	1. 如果满足以下所有条件，则在命令行中保留引号字符：
 *
 *	 - 没有 /S 开关
 *	 - 正好两个引号字符
 *	 - 两个引号字符之间没有特殊字符，其中特殊的字符之一是：&<>()@^|
 *	 - 两个引号字符之间有一个或多个空白字符
 *	 - 两个引号字符之间的字符串是可执行文件的名称。
 *
 *	 2. 否则，旧行为是检查第一个字符是否为引号字符，如果是，则去掉前导字符，并移除命令行上的最后一个引号字符，保留最后一个引号字符后面的任何文本。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 *
 * src/port/system.c
 *
 *-------------------------------------------------------------------------
 */

#if defined(WIN32) && !defined(__CYGWIN__)

#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include <fcntl.h>

#undef system
#undef popen

int pgwin32_system(const char *command)
{
	size_t		cmdlen = strlen(command);
	char	   *buf;
	int			save_errno;
	int			res;

	/*
	 * 创建命令字符串的 malloc 复制，外面加上一对额外的引号
	 */
	buf = malloc(cmdlen + 2 + 1);
	if (buf == NULL)
	{
		errno = ENOMEM;
		return -1;
	}
	buf[0] = '"';
	memcpy(&buf[1], command, cmdlen);
	buf[cmdlen + 1] = '"';
	buf[cmdlen + 2] = '\0';

	res = system(buf);

	save_errno = errno;
	free(buf);
	errno = save_errno;

	return res;
}


FILE * pgwin32_popen(const char *command, const char *type)
{
	size_t		cmdlen = strlen(command);
	char	   *buf;
	int			save_errno;
	FILE	   *res;

	/*
	 * 创建命令字符串的 malloc 复制，外面加上一对额外的引号
	 */
	buf = malloc(cmdlen + 2 + 1);
	if (buf == NULL)
	{
		errno = ENOMEM;
		return NULL;
	}
	buf[0] = '"';
	memcpy(&buf[1], command, cmdlen);
	buf[cmdlen + 1] = '"';
	buf[cmdlen + 2] = '\0';

	res = _popen(buf, type);

	save_errno = errno;
	free(buf);
	errno = save_errno;

	return res;
}

#endif
